function createChannelId(name) {
  const key = `channel-${name}`;
  let id = +localStorage.getItem(key) || 0;
  id++;
  localStorage.setItem(key, id.toString());
  return id;
}

class Channel extends BroadcastChannel {
  constructor(name, BroadcastCallback) {
    super(name);
    this.id = createChannelId(name);
    this.listeners = new Set();

    this.postMsg = (msg) => {
      this.postMessage({
        type: 'DATA',
        msg,
      });
    };

    this.postMessage({
      channelId: this.id,
      type: 'JOIN',
    });

    window.addEventListener('unload', () => {
      this.postMessage({
        channelId: this.id,
        type: 'LEAVE',
      });
    });

    this.addEventListener('message', (e) => {
      if (e.data.type === 'JOIN') {
        this.postMessage({
          channelId: this.id,
          type: 'JOIN_RESPONSE',
        });
        this.listeners.add(e.data.channelId);
      } else if (e.data.type === 'JOIN_RESPONSE') {
        this.listeners.add(e.data.channelId);
      } else if (e.data.type === 'DATA') {
        BroadcastCallback(e.data.msg);
      } else if (e.data.type === 'LEAVE') {
        this.listeners.delete(e.data.channelId);
      }
    });
  }
}

function createChannel(name, BroadcastCallback) {
  return new Channel(name, BroadcastCallback);
}